package falcon.common;

import java.io.IOException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * <pre>
 * </pre>
 */
public final class Security {

	public static SecretKey generateKey(String value) {
		return generateKey(value.getBytes(Global.DEFAULT_CHARSET));
	}
	
	public static SecretKey generateKey(byte[] value) {
		SecretKey sctKey = null;
		try {
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
			random.setSeed(value);
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			keygen.init(128, random);
			SecretKey orgKey = keygen.generateKey();
			byte[] array = orgKey.getEncoded();
			sctKey = new SecretKeySpec(array, "AES");
		} catch (Exception e) {
			sctKey = null;
			Log.log(e, "");
		}
		return sctKey;
	}
	
	public static String encryptValue(SecretKey key, String value) {
		String hexStr = null;
		try {
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, key);
			byte[] array = value.getBytes(Global.DEFAULT_CHARSET);
			hexStr = byteArrToHexStr(cipher.doFinal(array));
		} catch (Exception e) {
			hexStr = null;
			Log.log(e, "");
		}
		return hexStr;
	}
	
	public static String decryptValue(SecretKey key, String hexStr) {
		String value = null;
		try {
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] byteArr = hexStrToByteArr(hexStr);
			byte[] array = cipher.doFinal(byteArr);
			value = new String(array, Global.DEFAULT_CHARSET);
		} catch (Exception e) {
			value = null;
			Log.log(e, "");
		}
		return value;
	}
	
	public static String encrypt(String[] keyArray, String value) {
		String hex = value;
		for (int i = 0; i < keyArray.length; i ++) {
			String k = keyArray[i];
			SecretKey key = generateKey(k);
			if (key == null) {
				return null;
			}
			hex = encryptValue(key, hex);
			if (hex == null) {
				return null;
			}
		}
		return hex;
	}
	
	public static String decrypt(String[] keyArray, String hex) {
		String value = hex;
		for (int i = keyArray.length - 1; i > -1; i --) {
			String k = keyArray[i];
			SecretKey key = generateKey(k);
			if (key == null) {
				return null;
			}
			value = decryptValue(key, value);
			if (value == null) {
				return null;
			}
		}
		return value;
	}
	
	private static String byteArrToHexStr(byte[] arr) {
		String str = s_encoder.encode(arr);
		// 去掉 RFC822 规定的BASE64 编码超过 76 个字符添加的换行
		StringBuilder sb = new StringBuilder(256);
		for (int i = 0; i < str.length(); i ++) {
			char ch = str.charAt(i);
			if (ch == '\n' || ch == '\r') {
				continue;
			}
			sb.append(ch);
		}
		return sb.toString();
	}
	
	private static byte[] hexStrToByteArr(String str) throws IOException {
		byte[] arr = s_decoder.decodeBuffer(str);
		return arr;
	}
	
	private static final BASE64Encoder s_encoder = new BASE64Encoder();
	private static final BASE64Decoder s_decoder = new BASE64Decoder();
}
